﻿/**
@file
    diehard_collapsible.js
@brief
    Copyright 2009 Creative Crew. All rights reserved.
@author
    William Chang
    Email: william@babybluebox.com
    Website: http://www.babybluebox.com
@version
    0.1
@date
    - Created: 2009-04-28
    - Modified: 2009-05-08
    .
@note
    Prerequisites:
    - jQuery http://www.jquery.com/
    - jquery.cookie http://www.stilbuero.de/2006/09/17/cookie-plugin-for-jquery/
    .
*/

/** Collapsible widget. */
// Tabs widget.
(function($){
// Plugin for jQuery.
$.fn.diehard_collapsible = function(options) {
// Validate prerequisites.
if(!$.cookie) {throw('Dependency Error: jQuery plugin cookie is missing.');}
// Iterate and return each selected element back to library's chain.
return this.each(function(_intIndex) {
    /** Hide panel. */
    function _hideCollapsiblePanel(eleHeader, eleBody) {
        $(eleHeader).addClass('collapsible-selected-hide');
        $(eleBody).get(0).style.display = 'none';
        return '0';
    }
    /** Show panel. */
    function _showCollapsiblePanel(eleHeader, eleBody) {
        $(eleHeader).removeClass('collapsible-selected-hide');
        $(eleBody).get(0).style.display = 'block';
        return '1';
    }
    /** Get state of panel. */
    function _getState(intPanelIndex) {
        if(!_boolCookieEnabled) {return '';}
        if(_strCookieValues[intPanelIndex] !== undefined) {
            return _strCookieValues[intPanelIndex];
        } else {
            return '';
        }
    }
    /** Set state of panel. */
    function _setState(intPanelIndex, strToggle) {
        if(!_boolCookieEnabled) {return false;}
        _strCookieValues[intPanelIndex] = strToggle;
        _setCookie();
        return true;
    }
    /** Get cookie. */
    function _getCookie() {
        var strValue = $.cookie(_strCookieName);
        if(typeof strValue === 'string') {
            _strCookieValues = strValue.split(',');
        } else {
            _strCookieValues = [];
        }
    }
    /** Set cookie. */
    function _setCookie() {
        var strValue = _strCookieValues.join(',');
        $.cookie(_strCookieName, strValue, {expires:7});
    }
    /** Set collapse panel. */
    this.setCollapsiblePanel = function(strPanelId, strCommand) {
        // Find elements by id.
        for(var intIndex = 0;intIndex < _elePanels.length;intIndex++) {
            if(_elePanels[intIndex].id == strPanelId) {
                // Get header and body from panel.
                var eleHeader = $('> .' + _eleThis.options.strCollapsibleHeaderCss, _elePanels[intIndex]).get(0);
                var eleBody = $('> .' + _eleThis.options.strCollapsibleBodyCss, _elePanels[intIndex]).get(0);
                // Execute command.
                switch(strCommand.toLowerCase()) {
                    case '1': case 'true': case 'show': case 'open':
                        _showCollapsiblePanel(eleHeader, eleBody);_setState(intIndex, '1');break;
                    case '0': case 'false': case 'hide': case 'close':
                        _hideCollapsiblePanel(eleHeader, eleBody);_setState(intIndex, '0');break;
                    default:
                        return false;
                }
                // Return element found.
                return _elePanels[intIndex];
            }
        }
        return false;
    }
    /** Create collapsible events. */
    function _createCollapsiblePanelEvents(intPanelIndex, eleHeader, eleBody) {
        var objAnimateParams = {};
        switch(_eleThis.options.strCollapsibleDirection.toLowerCase()) {
            case 'vertical':
                objAnimateParams = {opacity:'toggle', height:'toggle'};break;
            case 'horizontal':
                objAnimateParams = {opacity:'toggle', width:'toggle'};break;
            default:
                return;
        }
        $(eleHeader).toggle(function(e) {
            // Has toggled, then trigger next method.
            if($(eleBody).css('display') == 'none') {$(this).trigger('click');return;}
            // Animate hide.
            if(_eleThis.options.fnBeforeStart) {_eleThis.options.fnBeforeStart.call(this, '0');}
            $(eleBody).animate(objAnimateParams, 'fast', function() {
                // Hide panel.
                _hideCollapsiblePanel(eleHeader, eleBody);
                _setState(intPanelIndex, '0');
            });
            if(_eleThis.options.fnAfterStop) {_eleThis.options.fnAfterStop.call(this, '0');}
        }, function(e) {
            // Animate show.
            if(_eleThis.options.fnBeforeStart) {_eleThis.options.fnBeforeStart.call(this, '1');}
            $(eleBody).animate(objAnimateParams, 'fast', function() {
                // Show panel.
                _showCollapsiblePanel(eleHeader, eleBody);
                _setState(intPanelIndex, '1');
                if($.browser.msie) {$(this).get(0).style.removeAttribute('filter');}
            });
            if(_eleThis.options.fnAfterStop) {_eleThis.options.fnAfterStop.call(this, '1');}
        });
    }
    /** Create collapsible panels from markup code. */
    function _createCollapsiblePanels() {
        // Get panels.
        _elePanels = $('.' + _eleThis.options.strPanelCss, _eleRegion).get();
        if(_elePanels.length <= 0) {throw('Error: Collapsible panels not found.');}
        var objPanels = [_elePanels.length];
        // Setup cookie.
        if(_eleThis.options.strCookieNamespace.length > 0) {
            _strCookieName = _eleThis.options.strCookieNamespace + _eleThis.options.strPanelCss;
            _boolCookieEnabled = true;
            _getCookie();
        }
        // Setup each panel.
        for(var intIndex = 0;intIndex < _elePanels.length;intIndex++) {
            // Get header and body from panel.
            var eleHeader = $('> .' + _eleThis.options.strCollapsibleHeaderCss, _elePanels[intIndex]).get(0);
            var eleBody = $('> .' + _eleThis.options.strCollapsibleBodyCss, _elePanels[intIndex]).get(0);
            // Prepend and append markup code to header.
            var eleHeaderLeft = $('<span class=\"' + _eleThis.options.strCollapsibleHeaderCss + '-left\"></span>').prependTo(eleHeader).get(0);
            var eleHeaderRight = $('<span class=\"' + _eleThis.options.strCollapsibleHeaderCss + '-right\"></span>').appendTo(eleHeader).get(0);
            // Restore state.
            var strState = _getState(intIndex);
            _eleThis.setCollapsiblePanel(_elePanels[intIndex].id, strState);
            if(!$(eleHeader).hasClass('collapsible-selected-hide') && $(eleBody).css('display') == 'none') {$(eleHeader).addClass('collapsible-selected-hide');}
            // Bind events to header.
            _createCollapsiblePanelEvents(intIndex, eleHeader, eleBody);
            // Create object and append to array of objects.
            var objPanel = {};
            objPanel.elePanel = _elePanels[intIndex];
            objPanel.eleHeader = eleHeader;
            objPanel.eleBody = eleBody;
            objPanel.strState = strState;
            objPanels[intIndex] = objPanel;
        }
        if(_eleThis.options.fnLoad) {_eleThis.options.fnLoad.call(this, objPanels);}
    }
    /** Load widget. */
    this.load = function _load() {
        _eleRegion = _eleThis;
        _createCollapsiblePanels();
    }
    /** Init library. */
    this.init = function init(options) {
        var defaults = {
            strPanelCss:'panel-collapsible',
            strCollapsibleHeaderCss:'panel-collapsible-header',
            strCollapsibleBodyCss:'panel-collapsible-body',
            strCookieNamespace:'domain_',
            strCollapsibleDirection:'vertical',
            fnLoad:null,
            fnBeforeStart:null,
            fnAfterStop:null
        };
        return $.extend(defaults, options);
    }

    // Fields.
    var _elePanels = [];
    var _eleRegion;
    var _boolCookieEnabled = false;
    var _strCookieName;
    var _strCookieValues = [];
    // Procedural.
    var _eleThis = this;
    _eleThis.options = _eleThis.init(options);
    _eleThis.load();
});
};
})(jQuery);